/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* * Anastasia Izmaylova - A.Izmaylova@cwi.nl - CWI
*******************************************************************************/
package lang.java.jdt.internal;
import java.util.Stack;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.VariableDeclaration;
public abstract class BindingsResolver implements IBindingsResolver {
private Stack<ASTNode> scopeStack;
private Stack<ITypeBinding> typeStack;
private BindingConverter bindingConverter;
public BindingsResolver(final BindingConverter bindingConverter) {
this.bindingConverter = bindingConverter;
this.scopeStack = new Stack<ASTNode>();
this.typeStack = new Stack<ITypeBinding>();
}
public void resolveBindings(ASTNode node) {
if(node instanceof AbstractTypeDeclaration) resolveBindings((AbstractTypeDeclaration) node);
else if(node instanceof AnnotationTypeMemberDeclaration) resolveBindings((AnnotationTypeMemberDeclaration) node);
else if(node instanceof AnonymousClassDeclaration) resolveBindings((AnonymousClassDeclaration) node);
else if(node instanceof EnumConstantDeclaration) resolveBindings((EnumConstantDeclaration) node);
else if(node instanceof Expression) resolveBindings((Expression) node);
else if(node instanceof FieldDeclaration) resolveBindings((FieldDeclaration) node);
else if(node instanceof ImportDeclaration) resolveBindings((ImportDeclaration) node);
else if(node instanceof MemberRef) resolveBindings((MemberRef) node);
else if(node instanceof MethodDeclaration) resolveBindings((MethodDeclaration) node);
else if(node instanceof MethodRef) resolveBindings((MethodRef) node);
else if(node instanceof PackageDeclaration) resolveBindings((PackageDeclaration) node);
else if(node instanceof Statement) resolveBindings((Statement) node);
else if(node instanceof Type) resolveBindings((Type) node);
else if(node instanceof TypeParameter) resolveBindings((TypeParameter) node);
else if(node instanceof VariableDeclaration) resolveBindings((VariableDeclaration) node);
}
public void manageStacks(ASTNode n, boolean push) {
boolean isScope = false;
ITypeBinding tb = getTypeDeclarationBinding(n);
if (tb != null) {
if (push) {
typeStack.push(tb);
bindingConverter.pushInitializerCounterStack();
} else {
typeStack.pop();
bindingConverter.popInitializerCounterStack();
}
isScope = true;
} else {
if (getMethodDeclarationBinding(n) != null)
isScope = true;
}
if (isScope) {
if (push) {
scopeStack.push(n);
bindingConverter.pushAnonymousClassCounterStack();
} else {
scopeStack.pop();
bindingConverter.popAnonymousClassCounterStack();
}
}
}
private ITypeBinding getTypeDeclarationBinding(ASTNode n) {
if (n instanceof AbstractTypeDeclaration) {
return ((AbstractTypeDeclaration) n).resolveBinding();
} else if (n instanceof AnonymousClassDeclaration) {
return ((AnonymousClassDeclaration) n).resolveBinding();
}
return null;
}
private IValue getMethodDeclarationBinding(ASTNode n) {
if (n instanceof MethodDeclaration) {
return bindingConverter.getEntity(((MethodDeclaration) n).resolveBinding());
} else if (n instanceof Initializer) {
ITypeBinding parentType = typeStack.peek();
return bindingConverter.getEntity((Initializer) n, parentType);
}
return null;
}
public void resolveBindings(AbstractTypeDeclaration node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(AnnotationTypeMemberDeclaration node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(AnonymousClassDeclaration node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(ImportDeclaration node) {
IBinding binding = node.resolveBinding();
if(binding instanceof IMethodBinding) importBinding((IMethodBinding) binding);
else if (binding instanceof ITypeBinding) importBinding((ITypeBinding) binding);
else if (binding instanceof IVariableBinding) importBinding((IVariableBinding) binding);
}
public void resolveBindings(MemberRef node) { /* Java doc */ }
public void resolveBindings(MethodDeclaration node) {
importBinding(node.resolveBinding());
importBinding(node.resolveBinding().getReturnType());
}
public void resolveBindings(MethodRef node) { /* Java doc */ }
public void resolveBindings(Name node) {
IBinding binding = node.resolveBinding();
if(binding instanceof IMethodBinding)
importBinding((IMethodBinding) binding);
else if(binding instanceof IPackageBinding)
importBinding((IPackageBinding) binding);
else if(binding instanceof IVariableBinding)
importBinding((IVariableBinding) binding);
if(node.resolveTypeBinding() != null)
importBinding(node.resolveTypeBinding());
}
public void resolveBindings(PackageDeclaration node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(Type node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(TypeParameter node) {
importBinding(node.resolveBinding());
}
public void resolveBindings(FieldDeclaration node) {
importBinding(node.getType().resolveBinding());
}
public void resolveBindings(VariableDeclaration node) {
IVariableBinding variableBinding = node.resolveBinding();
importBinding(variableBinding);
importBinding(variableBinding.getType());
}
public void resolveBindings(ClassInstanceCreation node) {
importBinding(node.resolveConstructorBinding());
importBinding(node.resolveTypeBinding());
}
public void resolveBindings(ConstructorInvocation node) {
importBinding(node.resolveConstructorBinding());
importBinding(node.resolveConstructorBinding().getReturnType());
}
public void resolveBindings(EnumConstantDeclaration node) {
importBinding(node.resolveConstructorBinding());
importBinding(node.resolveVariable());
}
public void resolveBindings(SuperConstructorInvocation node) {
importBinding(node.resolveConstructorBinding());
importBinding(node.resolveConstructorBinding().getReturnType());
}
public void resolveBindings(FieldAccess node) {
importBinding(node.resolveFieldBinding());
importBinding(node.resolveTypeBinding());
}
public void resolveBindings(SuperFieldAccess node) {
importBinding(node.resolveFieldBinding());
importBinding(node.resolveTypeBinding());
}
public void resolveBindings(MethodInvocation node) {
importBinding(node.resolveMethodBinding());
importBinding(node.resolveTypeBinding());
}
public void resolveBindings(SuperMethodInvocation node) {
importBinding(node.resolveMethodBinding());
importBinding(node.resolveTypeBinding());
}
private void resolveBindings(Expression node) {
if(node instanceof ClassInstanceCreation) resolveBindings((ClassInstanceCreation) node);
else if(node instanceof FieldAccess) resolveBindings((FieldAccess) node);
else if(node instanceof SuperFieldAccess) resolveBindings((SuperFieldAccess) node);
else if(node instanceof MethodInvocation) resolveBindings((MethodInvocation) node);
else if(node instanceof SuperMethodInvocation) resolveBindings((SuperMethodInvocation) node);
else if(node instanceof Name) resolveBindings((Name) node);
else importBinding(node.resolveTypeBinding());
}
private void resolveBindings(Statement node) {
if(node instanceof ConstructorInvocation) resolveBindings((ConstructorInvocation) node);
else if(node instanceof SuperConstructorInvocation) resolveBindings((SuperConstructorInvocation) node);
}
/*
* Methods to be implemented
*/
abstract public void importBinding(IMethodBinding binding);
abstract public void importBinding(IPackageBinding binding);
abstract public void importBinding(ITypeBinding binding, Initializer initializer);
abstract public void importBinding(IVariableBinding binding, Initializer initializer);
private void importBinding(ITypeBinding binding) {
if((!scopeStack.empty()) && (scopeStack.peek() instanceof Initializer))
importBinding(binding, (Initializer) scopeStack.peek());
else importBinding(binding, null);
}
private void importBinding(IVariableBinding binding) {
if((!scopeStack.empty()) && (scopeStack.peek() instanceof Initializer))
importBinding(binding, (Initializer) scopeStack.peek());
else importBinding(binding, null);
}
public ITypeBinding getEnclosingType() {
if(!typeStack.empty()) return typeStack.peek();
return null;
}
public Stack<ITypeBinding> getEnclosingTypes() {
return typeStack;
}
public ASTNode getEnclosingScope() {
if(!scopeStack.empty()) return scopeStack.peek();
return null;
}
}